#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#include "MSTK.h"
#include <mpi.h>

int main(int argc, char *argv[]) {
  int i, ok, dim;
  char mname[256],filename[256];
  char buf[256];
  char subfilename[256];
  Mesh_ptr mesh, recv_mesh, *submeshes;
  RepType rtype;
  /* default divide into two parts */
  int num, rank;

  /* Initialize MSTK - Always do this even if it does not seem to
     matter in this version of MSTK */
  MSTK_Init();  
  
  /* initialize MPI */
  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&num);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);

  /* Load the mesh */
  strcpy(mname,argv[1]);
  strcpy(filename,mname);
  strcat(filename,".mstk");
  dim = atoi(argv[3]);

  /* master process read in and divide the mesh */
  if(rank == 0) { 
    mesh = MESH_New(UNKNOWN_REP);
    ok = MESH_InitFromFile(mesh,filename);
    if (!ok) {
      fprintf(stderr,"Cannot open input file %s\n\n\n",filename);
      exit(-1);
    }
    fprintf(stdout,"mstk mesh %s read in successfully\n",filename);

    /* Partition the mesh*/
    rtype = MESH_RepType(mesh);
    submeshes = (Mesh_ptr *)MSTK_malloc((num)*sizeof(Mesh_ptr));
    ok = MESH_Partition(mesh,submeshes,num);
    fprintf(stdout,"%s has been partitioned into %d submeshes\n",filename,num);
    
    /* operation on submeshes */
    for(i = 0; i < num; i++) {  
      /* build pboundary */
      MESH_BuildPBoundary(mesh,submeshes[i]);
      /* add ghost */
      MESH_AddGhost(mesh,submeshes[i],i,1);
      if(i > 0) {
	/* send mesh */
	MESH_SendMesh(submeshes[i],i,MPI_COMM_WORLD);
      }
    }
  }

  /* receive mesh */
  if(rank == 0)
    /* submesh on the root */
    recv_mesh = submeshes[0];
  else {
    recv_mesh = MESH_New(UNKNOWN_REP);
    MESH_RecvMesh(recv_mesh,dim,0,rank,MPI_COMM_WORLD);
    fprintf(stdout,"submesh %d received\n",rank);
  }

  strcpy(subfilename,mname);
  itoa(rank,buf);
  strcat(subfilename,buf);
  strcat(subfilename,"-recv.mstk");
  PMESH_WriteToFile(recv_mesh,subfilename,R1);

  /* clean up */
  MPI_Barrier(MPI_COMM_WORLD);
  /*
  MESH_Delete(recv_mesh);
  */  
  MESH_Delete(recv_mesh);
  if(rank == 0) {
    /* Deleting of mesh is not necessary if this the end of the program */
    for (i = 1; i < num; i++)
      MESH_Delete(submeshes[i]);
    /* Write out a copy of the mesh */
    strcpy(filename,mname);
    strcat(filename,"-copy.mstk");
    MESH_WriteToFile(mesh,filename,rtype);

  }
 
  MPI_Finalize();
  return 1;
}

